﻿using System;
using System.IO;
using System.Windows.Forms;

namespace DominionWar
{
    class Simulation
    {
        private Random Rand;

        private Fleet Fleet1;
        private Fleet Fleet2;

        private int round = 0;
        private String battleReport = "\r\n"; //Initial newline character just to keep as close to demonstration solution as possible

        public Simulation(String seedValue, String fleet1FilePath, String fleet2FilePath)
        {
            try
            {
                int seed = Convert.ToInt32(seedValue);
                if (seed < 0)
                    throw new System.ArgumentException();
                this.Rand = new Random(seed);
            }
            catch (Exception ex)
            {
                if (ex is System.OverflowException ||
                    ex is System.FormatException ||
                    ex is System.ArgumentException)
                    throw new SimulationError("Invalid seed value entered");
                else
                    throw;
            }

            Setup(fleet1FilePath, fleet2FilePath);

            while (this.Fleet1.HasShipsAlive() && this.Fleet2.HasShipsAlive())
                NextRound();
        }

        public void Setup(String filename1, String filename2)
        {
            this.Fleet1 = new Fleet(filename1);
            this.Fleet2 = new Fleet(filename2);
        }

        private void NextRound()
        {
            round++;

            Attack(Fleet1, Fleet2);
            Attack(Fleet2, Fleet1);

            Fleet1.RemoveDestroyedShips();
            Fleet2.RemoveDestroyedShips();

            RechargeShields(Fleet1);
            RechargeShields(Fleet2);

            this.battleReport += Fleet1.getRoundReport(round);
            this.battleReport += Fleet2.getRoundReport(round);
        }

        private void Attack(Fleet fleet, Fleet enemies)
        {
            foreach (BaseShip ship in fleet.GetShips())
            {
                int damage = ship.GetWeaponBaseDamage() + Rand.Next(ship.GetWeaponRandomDamage());
                BaseShip target = enemies.GetShip(Rand.Next(enemies.ShipCount()));

                target.Hit(damage);
            }
        }

        private void RechargeShields(Fleet fleet)
        {
            foreach (BaseShip ship in fleet.GetShips())
                ship.RechargeShield();
        }

        public String getBattleReport()
        {
            Fleet survivingFleet = null;
            Fleet destroyedFleet = null;
            if (Fleet1.HasShipsAlive())
            {
                survivingFleet = Fleet1;
                destroyedFleet = Fleet2;
            }
            else if (Fleet2.HasShipsAlive())
            {
                survivingFleet = Fleet2;
                destroyedFleet = Fleet1;
            }

            if (survivingFleet == null)
            {
                this.battleReport += "After round " + round.ToString() + " the battle has been a draw with both sides destroyed\r\n";
            }
            else
            {
                this.battleReport += "After round " + round.ToString() + " the " + survivingFleet.GetName() + " has won" + "\r\n";
                this.battleReport += "  " + destroyedFleet.ShipsLostCount().ToString() + " enemy ships destroyed" + "\r\n";
                this.battleReport += "  " + survivingFleet.ShipsLostCount().ToString() + " ships lost" + "\r\n";
                this.battleReport += "  " + survivingFleet.ShipCount().ToString() + " ships survived" + "\r\n";
                this.battleReport += survivingFleet.getDamageReport();
            }
            return this.battleReport;
        }
    }
}